<?php

/**
 * 学生作业信息模型
 */
class Taskinfo_model extends CI_Model {

	/**
	 * 构造方法，用来创建数据表
	 */
	public function __construct() {
		if ($this->db->table_exists('taskinfo') != true) {
			$this->creatTaskinfoTable();
		}
	}

	/**
	 * 创建学生作业信息数据表
	 * 先设置字段，再设置索引
	 * @return void
	 */
	public function creatTaskinfoTable() {
		// 加载数据库工厂类
		$this->load->dbforge();
		// 设置字段信息
		$fields = array(
			'stu_id'    => array(
				'type'           => 'INT',
				'constraint'     => 5,
				'unsigned'       => TRUE,
				'auto_increment' => TRUE,
			),
			'stuname'   => array(
				'type'       => 'VARCHAR',
				'constraint' => '100',
			),
			'stunumber' => array(
				'type'       => 'VARCHAR',
				'constraint' => '10',
			),
			'stuclass'  => array(
				'type'       => 'INT',
				'constraint' => '1',
			),
			'stuurl'    => array(
				'type'       => 'VARCHAR',
				'constraint' => '200',
			),
		);
		// 添加字段
		$this->dbforge->add_field($fields);
		// 设置索引
		$this->dbforge->add_key('stu_id', TRUE);
		$this->dbforge->add_key('stuname');
		$this->dbforge->add_key('stuclass');
		// 根据以上信息创建表
		$this->dbforge->create_table('taskinfo');
	}

	/**
	 * 存储学生提交的信息
	 * @param array $data 用户提交信息
	 * @return void
	 */
	public function add(array $data) {
		$this->db->insert('taskinfo', $data);
	}

	/**
	 * 获取taskinfo表中的所有信息
	 * 然后以数组的形式返回
	 * @return array 表中的全部信息
	 */
	public function getAll() {
		return $this->db->get('taskinfo')->result_array();
	}

	/**
	 * 生成学期周次节点
	 * @param  string $start 课程开始日期
	 * @return array 		 包含19周上课时间节点的数组
	 */
	public function weekly($start = '2017-8-30') {
		for ($i = 0; $i < 19; $i++) {
			$data[$i] = strtotime("+" . $i . " week", strtotime($start));
		}
		return $data;
	}

	/**
	 * 获取学生仓库存储所在的网站、用户名和仓库名称
	 * @param  string $str	学生仓库地址
	 * @return mixed 		如果匹配成功，则返回数组，否则返回false
	 */
	public function getUserRepo($str = '') {
		// 去掉.git
		$pattern = '/.git$/';
		$str     = preg_replace($pattern, '', $str);
		// 获取站点、用户名、仓库名
		$pattern = '@\/\/(.*?)\/(.*?)\/(.*)@';
		if (preg_match($pattern, $str, $matched)) {
			$data['site']     = $matched[1];
			$data['username'] = $matched[2];
			$data['repo']     = $matched[3];
			return $data;
		} else {
			return false;
		}
	}

	/**
	 * 使用curl库获取在线信息
	 * @param  string  $url    在线地址
	 * @param  boolean $decode 是否将json转化为数组
	 * @return mixed           字符串或者数组
	 */
	public function getOnlineData($url = '', $decode = TRUE) {
		// 初始化curl
		$ch = curl_init($url);
		//
		// 设置cURL配置项
		//
		// CURLOPT_HEADER 为真时，在输出结果中包含header信息
		// CURLOPT_RETURNTRANSFER 为真时，将结果以字符串的形式返回，为假时，结果直接在浏览器中显示
		//
		curl_setopt($ch, CURLOPT_HEADER, 0);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在
		// 执行crul，并将返回的结果保存到变量$data中。
		$data = curl_exec($ch);
		// 将json数据转换为数组
		if ($decode) {
			$data = json_decode($data, true);
		}
		// 关闭curl资源
		curl_close($ch);
		// var_dump($data);
		return $data;
	}

	/**
	 * 获取gitee.com站点的推送信息
	 * @param  string $user 用户名
	 * @param  string $repo 仓库名
	 * @return array        数组格式的推送信息
	 */
	public function getGiteeCommits($user = '', $repo = '') {
		// 拼接gitee API地址
		$url = "https://gitee.com/api/v5/repos/" . $user . "/" . $repo . "/commits";
		// 获取数组
		$data = $this->getOnlineData($url);
		return $data;
	}

	/**
	 * 获取coding.net站点的推送信息
	 * @param  string $user 用户名
	 * @param  string $repo 仓库名
	 * @return array        数组格式的推送信息
	 */
	public function getCodingnetCommits($user = '', $repo = '') {
		// 拼接gitee API地址
		$url = "https://coding.net/api/user/" . $user . "/project/" . $repo . "/git/commits/master%252F?page=1&pageSize=50";
		// 获取数组
		$data = $this->getOnlineData($url);
		if (isset($data['data']['commits']['list'])) {
			return $data['data']['commits']['list'];
		} else {
			return false;
		}
	}

	/**
	 * 获取每周作业推送次数
	 * @param  array  $commits 学生作业推送信息数组
	 * @return array           学生每周作业推送次数
	 */
	public function getCommitByWeek(array $commitDate = array()) {
		// 先得到学期时间节点
		$week = $this->weekly();
		// 初始化数组
		$array = array();
		// 逐一比较
		for ($i = 0; $i < 19; $i++) {
			$array[$i] = 0;
			foreach ($commitDate as $key => $value) {
				if ($value >= $week[$i] && $value <= $week[$i + 1]) {
					$array[$i]++;
				}
			}
		}
		return $array;
	}

	/**
	 * 获取gitee.com站点中的作业推送日期
	 * @param  array  $commits 作业信息原始数组
	 * @return mixed           作业推送日期或者false
	 */
	public function getGiteeCommitDate(array $commits = array()) {
		foreach ($commits as $key => $value) {
			// 2017-11-15T17:54:42+08:00,提取其日期
			// 首先判断是否有值
			if (isset($value['commit']['author']['date'])) {
				$array[$key] = strtotime($value['commit']['author']['date']);
			} else {
				return false;
			}
		}
		return $array;
	}

	/**
	 * 获取coding.net站点中的作业推送日期
	 * @param  array  $commits 作业信息原始数组
	 * @return array           作业推送日期
	 */
	public function getCodingnetCommitDate(array $commits = array()) {
		foreach ($commits as $key => $value) {
			// commitTime	1498376546000
			// 需要截取前十位字符组成时间
			if (isset($value['commitTime'])) {
				$array[$key] = substr($value['commitTime'], 0, 10);
			} else {
				return false;
			}
		}
		return $array;
	}

	/**
	 * 返回具体学生作业信息，包括提交次数和提交周次
	 * @param  integer $id	学生在数据库中的编号
	 * @return mixed   		包含学生信息的多维数组
	 */
	public function creatStuTaskInfo($id = 0) {
		// 获取指定用户信息
		$array = array('stu_id' => $id);
		$data  = $this->db->where($array)->get('taskinfo')->result_array();
		// 获取用户名、站点信息、仓库信息
		$data['userrepo'] = $this->getUserRepo($data[0]['stuurl']);
		// 针对gitee.com站点获取信息
		if ($data['userrepo']['site'] == 'git.oschina.net' || $data['userrepo']['site'] == 'gitee.com') {
			// 获取gitee.com全部推送信息
			$data['totalcommits'] = $this->getGiteeCommits($data['userrepo']['username'], $data['userrepo']['repo']);
			// 分析并生成推送信息的日期信息
			if ($data['totalcommits']) {
				$data['commitDate'] = $this->getGiteeCommitDate($data['totalcommits']);
				if ($data['commitDate']) {
					// 生成每周推送次数信息
					$data['weekly'] = $this->getCommitByWeek($data['commitDate']);
					return $data;
				} else {
					return false;
				}
			} else {
				return false;
			}

		}
		if ($data['userrepo']['site'] == 'git.coding.net') {
			// 获取coding.net全部推送信息
			$data['totalcommits'] = $this->getCodingnetCommits($data['userrepo']['username'], $data['userrepo']['repo']);
			// 分析并生成推送信息的日期信息
			if ($data['totalcommits']) {
				$data['commitDate'] = $this->getCodingnetCommitDate($data['totalcommits']);
				if ($data['commitDate']) {
					// 生成每周推送次数信息
					$data['weekly'] = $this->getCommitByWeek($data['commitDate']);
					return $data;
				} else {
					return false;
				}
			} else {
				return false;
			}

		}
		// 如果不是上述站点，则返回假
		return false;
	}

}
